class MapClass {
    constructor(centerPoint, options) {
        let that = this;
        const tileLayer = new maptalks.TileLayer("base", {
            urlTemplate: "https://gss{s}.bdstatic.com/8bo_dTSlRsgBo1vgoIiO_jowehsv/tile/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&udt=20210801",
            subdomains: [0, 1, 2, 3],
            attribution: '&copy; <a target="_blank" href="http://map.baidu.com">Baidu</a>',
            //cssFilter: "sepia(100%) invert(90%)",
        });
        this.base = {
            baseLayer: tileLayer,
            spatialReference: {
                projection: "baidu",
            },
        };
        const map = new maptalks.Map(
            "map",
            this.extend(
                this.extend({
                        center: centerPoint,
                        zoom: 14,
                        maxZoom: 20,
                        minZoom: 12,
                        //pitch: 45,
                        centerCross: true,
                        attribution: true,
                        zoomControl: true, // add zoom control
                        scaleControl: true, // add scale control
                        overviewControl: true, // add overview control
                        layers: [],
                        bearing: -1.800000000000182,
                    },
                    options || {}
                ),
                this.base
            )
        );
        this.mapObject = map;
        this.query = jQuery;
        var metric = new maptalks.control.Scale({
            position: "top-right",
            maxWidth: 150,
            metric: true,
            imperial: false,
        });
        map.addControl(metric);
        this.animate({
            center: centerPoint,
            zoom: 12,
            pitch: 35,
            bearing: 0,
        }, {
            duration: 3000,
        });
        this.isScene = false;
        this.is3D = false;
        const starPicLayer = this.drawStarpic();
        map.addControl(
            new maptalks.control.Toolbar({
                position: { top: 195, left: 20 },
                vertical: true,
                items: [{
                        item: that.isScene ? "关闭实景" : "开启实景",
                        click: function(e) {
                            that.isScene = that.isScene ? false : true;
                            starPicLayer[that.isScene ? "show" : "hide"]();
                            e.dom.innerHTML = that.isScene ? "关闭实景" : "开启实景";
                        },
                    },
                    {
                        item: !that.is3D ? "关闭3D" : "开启3D",
                        click: function(e) {
                            that.is3D = that.is3D ? false : true;
                            map.setView({
                                pitch: !that.is3D ? 35 : 0,
                            });
                            e.dom.innerHTML = !that.is3D ? "关闭3D" : "开启3D";
                        },
                    },
                ],
            })
        );
        return this;
    }
    extend(ops, target) {
        target = target || this;
        for (let n in ops) target[n] = ops[n];
        return target;
    }
    getStatus(container) {
        let that = this;
        this.mapObject.on("zoomend moving moveend", () => {
            var message = document.getElementById(container);

            var extent = that.mapObject.getExtent(),
                ex = [
                    "{",
                    "xmin:" + extent.xmin.toFixed(5),
                    ", ymin:" + extent.ymin.toFixed(5),
                    ", xmax:" + extent.xmax.toFixed(5),
                    ", ymax:" + extent.xmax.toFixed(5),
                    "}",
                ].join("");
            var center = that.getCenter();
            var mapStatus = [
                "Center : [" + [center.x.toFixed(5), center.y.toFixed(5)].join() + "]",
                //"Extent : " + ex,
                "Size : " + that.mapObject.getSize().toArray().join(),
                "Zoom : " + that.mapObject.getZoom(),
                //"MinZoom : " + map.getMinZoom(),
                //"MaxZoom : " + map.getMaxZoom(),
                "Projection : " + that.mapObject.getProjection().code,
            ];

            message.innerHTML = mapStatus.join("<br>");
        });
        return this;
    }
    on(events, callback) {
        this.mapObject.on(events, callback);
        return this;
    }
    drawPolygons(request, options) {
        options = options || {};
        let that = this;
        let polygons = [];
        let setDrawPolygons = (idx, coordinates, properties) => {
            const polygon = new maptalks.MultiPolygon(coordinates, {
                    symbol: that.extend(
                        that.extend({
                                lineWidth: 1,
                                lineColor: "#ccc",
                                polygonFill: "#91b0e3",
                                polygonOpacity: 0.5,
                                textFaceName: "sans-serif",
                                textWeight: "normal", //'bold', 'bolder'
                                textStyle: "normal", //'italic', 'oblique'
                                textSize: 20,
                                textFill: "#333",
                                textHaloFill: "#fff",
                            },
                            options.symbol || {}
                        ), {
                            textName: properties.name, //value from name in geometry's properties
                        }
                    ),
                    properties: {
                        //altitude: altitude,
                        id: properties.id,
                        index: idx,
                        properties: properties,
                    },
                })
                .on("mouseenter", function(e) {
                    e.target.updateSymbol(
                        that.extend({
                                lineWidth: 2,
                                lineColor: "#999",
                                polygonFill: "#91b0e3",
                                polygonOpacity: 0,
                            },
                            options.mouseEnterSymbol || {}
                        )
                    );
                })
                .on("mouseout", function(e) {
                    e.target.updateSymbol(
                        that.extend({
                                lineWidth: 1,
                                lineColor: "#ccc",
                                polygonFill: "#91b0e3",
                                polygonOpacity: 0.5,
                            },
                            options.mouseOutSymbol || {}
                        )
                    );
                });
            polygon.on("click", function(e) {
                //console.log(e);
                that.setCenter(properties.center);
                that.animate({
                    center: properties.center,
                    zoom: 14,
                    pitch: 35,
                    bearing: 0,
                }, {
                    duration: 3000,
                });
            });
            polygons.push(polygon);
            let copyPolygon = polygon.copy();
            let tileLayer = new maptalks.TileLayer("polygon_" + polygons.length, {
                    urlTemplate: "https://gss{s}.bdstatic.com/8bo_dTSlRsgBo1vgoIiO_jowehsv/tile/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&udt=20210801",
                    subdomains: [0, 1, 2, 3],
                })
                .setMask(copyPolygon)
                .addTo(that.mapObject);
            tileLayer.zIndex = 999998;
            tileLayer.hide();
        };
        let promise = new Promise((resolve, reject) => {
            request
                .then((features) => {
                    features.forEach((g, i) => {
                        const properties = g.properties;
                        const coordinates = g.geometry.coordinates;
                        setDrawPolygons(i, coordinates, properties);
                    });
                    resolve(polygons);
                })
                .catch((e) => {
                    reject(e);
                });
        });
        promise.then((polygons) => {
            new maptalks.VectorLayer("vector-polygon", polygons).addTo(
                that.mapObject
            );
        });
        return this;
    }
    drawLines(request, options) {
        options = options || {};
        let that = this;
        let setDrawLine = (ops) => {
            var line = new maptalks.LineString(
                ops.list,
                that.extend({
                        arrowStyle: null, // arrow-style : now we only have classic
                        arrowPlacement: "vertex-last", // arrow's placement: vertex-first, vertex-last, vertex-firstlast, point
                        visible: true,
                        editable: true,
                        cursor: null,
                        shadowBlur: 0,
                        shadowColor: "black",
                        draggable: false,
                        dragShadow: false, // display a shadow during dragging
                        drawOnAxis: null, // force dragging stick on a axis, can be: x, y
                        symbol: {
                            textName: ops.text,
                            textPlacement: "line",
                            textSize: 12,
                            lineColor: "#1bbc9b",
                            lineWidth: 12,
                        },
                    },
                    options.lineString || {}
                )
            );

            new maptalks.VectorLayer("vector_" + Math.random(), line).addTo(
                that.mapObject
            );
            options.clickHandle && line.on("click", options.clickHandle);
        };
        request.then((list) => {
            list.forEach((n) => {
                setDrawLine({
                        text: n.name,
                        list: n.points,
                    },
                    that.mapObject
                );
            });
        });

        return this;
    }
    drawMarkers(request, options) {
        options = options || {};
        let that = this;
        let markers = [];
        request.then((points) => {
            points.forEach((point) => {
                let marker = new maptalks.Marker(
                    point.point,
                    that.extend({
                            symbol: {
                                textName: point.data.title,
                                textSize: 16,
                                textFill: "block",
                                textDy: 16,
                                textOpacity: 1,
                                textHaloFill: "#fff",
                                textHaloRadius: 5,
                                textWrapWidth: null,
                                textWrapCharacter: "\n",
                                textLineSpacing: 0,
                                markerFile: point.data.icon, //"../assets/img/map.png",
                                markerWidth: 60,
                                markerHeight: 60,
                            },
                        },
                        options.markerSymbol || {}
                    )
                );
                var ops = {
                    title: point.data.title,
                    content: point.data.desc || point.data.title,
                };
                marker.setInfoWindow(ops);
                marker
                    .on("click", markerClickHandle)
                    .on("mouseenter", function(e) {
                        //update markerFill to highlight
                        marker.openInfoWindow();
                        e.target.updateSymbol(
                            that.extend({
                                    markerFill: "#f00",
                                    markerLineColor: "#fff",
                                    textSize: 30,
                                    markerWidth: 60,
                                    markerHeight: 60,
                                },
                                options.mouseEnterSymbol || {}
                            )
                        );
                    })
                    .on("mouseout", function(e) {
                        //reset color
                        marker.closeInfoWindow();
                        e.target.updateSymbol(
                            that.extend({
                                    markerFill: "#fff",
                                    textSize: 16,
                                    markerLineColor: "#1bbc9b",
                                    markerWidth: 60,
                                    markerHeight: 60,
                                },
                                options.mouseOutSymbol || {}
                            )
                        );
                    });
                markers.push(marker);
            });

            function markerClickHandle(e) {
                //console.log(e.target._coordinates, e);
                var data = findPointInfo(e.target._coordinates);
                if (data) {
                    var message = document.getElementById("message"),
                        msgText = document.getElementById("message_text"),
                        msgImage = document.getElementById("message_image");
                    message.addEventListener("click", function() {
                        message.style.display = "none";
                    });
                    msgText.innerHTML = data.title;
                    msgImage.innerHTML = "<img src='" + data.image + "' objectFit=''>";
                    message.style.display = "flex";
                }
            }

            function findPointInfo(point) {
                for (var i = 0; i < points.length; i++) {
                    if (
                        points[i].point[0] === point.x &&
                        points[i].point[1] === point.y
                    ) {
                        return points[i].data;
                    }
                }
            }

            that.mapObject.addLayer([new maptalks.VectorLayer("v", markers)]);
        });
        return this;
    }
    drawStarpic() {
        var tstyle = "pl";
        var udtVersion = "20190102";
        var tilelayer = new maptalks.TileLayer("traffic", {
            urlTemplate: "//maponline{s}.bdimg.com/starpic/?qt=satepc&u=x={x};y={y};z={z};v=009;type=sate&fm=46&app=webearth2&v=009&udt=20210819", //"http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
            subdomains: [0, 1, 2, 3],
        });
        tilelayer.zIndex = 999998;
        //tilelayer.setOpacity(0.8);
        // point为图块坐标，level为图块的级别
        // 当地图需要显示特定级别的特定位置的图块时会自动调用此方法，并提供这两个参数
        tilelayer.getTilesUrl = function(point, level) {
            if (!point || level < 0) {
                return null;
            }
            var row = point.x;
            var col = point.y;
            var url =
                "//mapsv0.bdimg.com/tile/?udt=" +
                udtVersion +
                "&qt=tile&styles=" +
                tstyle +
                "&x=" +
                row +
                "&y=" +
                col +
                "&z=" +
                level;
            return url;
        };
        this.mapObject.addLayer(tilelayer);
        tilelayer.hide();
        return tilelayer;
    }
    trafficCallback(data) {
        console.log(data);
    }
    drawTrafficLayer() {
        //禁止跨域，暂时停止使用
        var tstyle = "pl";
        var udtVersion = "20190102";
        var tilelayer = new maptalks.TileLayer("traffic", {
            urlTemplate: "//its.map.baidu.com/traffic/?qt=vtraffic&z={z}&x={x}&y={y}&udt=20210819&fn=map.trafficCallback", //"http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
            subdomains: [0, 1, 2, 3],
        });
        tilelayer.zIndex = 110;
        // point为图块坐标，level为图块的级别
        // 当地图需要显示特定级别的特定位置的图块时会自动调用此方法，并提供这两个参数
        tilelayer.getTilesUrl = function(point, level) {
            if (!point || level < 0) {
                return null;
            }
            var row = point.x;
            var col = point.y;
            var url =
                "//mapsv0.bdimg.com/tile/?udt=" +
                udtVersion +
                "&qt=tile&styles=" +
                tstyle +
                "&x=" +
                row +
                "&y=" +
                col +
                "&z=" +
                level;
            return url;
        };
        this.mapObject.addLayer(tilelayer);
        return this;
    }
    drawRoadTileLayer(options) {
        var tstyle = "pl";
        var udtVersion = "20190102";
        var tilelayer = new maptalks.TileLayer(
            (options && options.name) || "road", {
                urlTemplate: "//mapsv0.bdimg.com/tile/?udt=20190102&qt=tile&styles=pl&x={x}&y={y}&z={z}", //"http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
                subdomains: [0, 1, 2, 3],
            }
        );
        tilelayer.zIndex = 999999;
        // point为图块坐标，level为图块的级别
        // 当地图需要显示特定级别的特定位置的图块时会自动调用此方法，并提供这两个参数
        tilelayer.getTilesUrl = function(point, level) {
            if (!point || level < 0) {
                return null;
            }
            var row = point.x;
            var col = point.y;
            var url =
                "//mapsv0.bdimg.com/tile/?udt=" +
                udtVersion +
                "&qt=tile&styles=" +
                tstyle +
                "&x=" +
                row +
                "&y=" +
                col +
                "&z=" +
                level;
            return url;
        };
        //this.mapObject.addLayer(tilelayer);
        tilelayer.addTo(this.mapObject);
        return tilelayer;
    }
    getCenter() {
        return this.mapObject.getCenter();
    }
    setCenter(options) {
        this.mapObject.setCenter(options);
        return this;
    }
    animate(options, speed) {
        this.mapObject.animateTo(options, speed);
        return this;
    }
}